package com.hengpeng.msls.controller;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.google.gson.Gson;
import com.hengpeng.common.exception.ServiceResult;
import com.hengpeng.common.persist.entity.AbstractEntity.BoolValue;
import com.hengpeng.common.util.MoneyUtil;
import com.hengpeng.common.util.StringHelper;
import com.hengpeng.itfinbase.constants.RespCodeConstants;
import com.hengpeng.itfinbase.constants.TransCodeConstants;
import com.hengpeng.itfinbase.en.BorrowStatus;
import com.hengpeng.itfinbase.en.RewardRedPacketStatus;
import com.hengpeng.itfinbase.en.InvestStatus;
import com.hengpeng.itfinbase.en.RewardUseType;
import com.hengpeng.itfinbase.message.ResponseMessage;
import com.hengpeng.itfinbase.message.partner.InvestBorrowerDetail;
import com.hengpeng.itfinbase.message.partner.InvestInfoRequestMsg;
import com.hengpeng.itfinbase.message.partner.PartnerTransType;
import com.hengpeng.itfinbase.message.partner.RedUseRequestMsg;
import com.hengpeng.itfinbase.persist.Account;
import com.hengpeng.itfinbase.persist.BorrowInfo;
import com.hengpeng.itfinbase.persist.Reward;
import com.hengpeng.itfinbase.persist.RewardRedpacket;
import com.hengpeng.itfinbase.persist.UserInfo;
import com.hengpeng.msls.constants.LSConstants;
import com.hengpeng.msls.constants.PartnerUtil;
import com.hengpeng.msls.tools.JsonUtils;
import com.hengpeng.msls.vo.SessionMember;
import com.hengpeng.msls.vo.invest.InvestInfoVo;
/**
 * <pre>
 * 投标控制器
 * </pre>
 * 
 * @author lugaofei 20151029
 */
@Controller
@RequestMapping("/investInfo")
public class InvestInfoController extends BaseController {
    /**
     * <pre>
     *       校验事项：
     *        1,投资人账户中必须有足够的资金进行投资。
     *        2,借款标的状态必须是：筹款中状态。
     *        3,投资金额必须在标的的最大投资金额和最小投资金额之间。
     *        4,校验投资金额是否已经超过剩余借款额度
     *       投资前操作：
     *        1,投资调用投资接口前，先占据投资额度(更新标的信息表中已募集金额,和已募集人数)
     *        2,设定投资支付时间限制，若超过时间限制还没有支付完成则释放投资额度。
     *        3,超过支付时间限制的投标，调用撤标接口。
     *        4,生成投资记录信息,状态为：投标中
     *       投资接口调用成功后操作：
     *        1,更新投资信息状态
     *        2,冻结投资人资金信息表中相关资金。
     *        3,添加资金流水表相关资金冻结流水。
     *        4,更新标的信息表中的已募集金额,已募集人数。
     *        5,判断标的是否已经金额达到募集金额，如果达到募集金额则设置标的状态为：募集结束
     *       投资接口调用失败后操作：
     *        1,释放投资额度
     *        2,更新投标信息状态为：失败
     *       投标实时返回和回调接口都需实现
     * </pre>
     * 
     * @param map
     * @param request
     * @param borrowInfoId
     *            标的id
     * @param investMoney
     *            投资金额
     * @param redPacketId
     *            使用的红包id
     * @return
     */
    @RequestMapping(value = "/doInvest")
    @ResponseBody
    public ServiceResult<ResponseMessage> doInvest(ModelMap map, HttpServletRequest request, String borrowInfoId,
            Long investMoney, Long redPacketId) {
        ServiceResult<ResponseMessage> result = new ServiceResult<ResponseMessage>();
        ResponseMessage response = new ResponseMessage();
        BorrowInfo borrowInfo = serviceFactory.getBorrowInfoService().getBorrowInfo(Long.parseLong(borrowInfoId),
                BorrowStatus.RAISE);
        SessionMember member = (SessionMember) request.getSession().getAttribute(LSConstants.CLIENT_SESSION_MEMBER);
        if (member == null) {
            result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
            result.setMessage("请先登录");
            result.setReturnValue(response);
            return result;
        }
        if (borrowInfo == null) {
            result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
            result.setMessage("标的不存在,或标的状态异常");
            result.setReturnValue(response);
            return result;
        }
        if (investMoney < (borrowInfo.getMinInvest() / 100) || investMoney > (borrowInfo.getMaxInvest() / 100)) {
            result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
            result.setMessage("投标金额不能小于最小投资额,并且不能大于最大投资额");
            result.setReturnValue(response);
            return result;
        }
        if ((investMoney * 100 - borrowInfo.getMinInvest()) % borrowInfo.getIncMoney() != 0) {
            result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
            result.setMessage("最小投标为:" + MoneyUtil.convertFenToYuan(borrowInfo.getMinInvest()) + "，增量金额必须为:"
                    + MoneyUtil.convertFenToYuan(borrowInfo.getIncMoney()) + "的整数倍");
            result.setReturnValue(response);
            return result;
        }
        if ((borrowInfo.getRaiseMoney() + investMoney * 100) > borrowInfo.getBorrowMoney()) {
            result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
            result.setMessage("投资额度已大于剩余融资额度");
            result.setReturnValue(response);
            return result;
        }
        if (member.getUser() == null) {
            result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
            result.setMessage("当前用户信息异常,请重新登录");
            result.setReturnValue(response);
            return result;
        }
        if (member.getUser().getIsInvestor() == BoolValue.NO) {
            result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
            result.setMessage("对不起,您不是投资人角色");
            result.setReturnValue(response);
            return result;
        }
        if (member.getUser().getId().equals(borrowInfo.getBorrowUserId())) {
            result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
            result.setMessage("对不起,您不能投资自己的借款标");
            result.setReturnValue(response);
            return result;
        }
        UserInfo user = serviceFactory.getUserInfoService().getUserInfoById(member.getUser().getId());
        if (StringHelper.isEmpty(user.getTrustAccountId())) {
            result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
            result.setMessage("请您先开通托管账户");
            result.setReturnValue(response);
            return result;
        }
        /**
         * 红包可用性校验,根据红包对应的奖品类型进行判断
         */
        if (redPacketId != null) {
            RewardRedpacket rewardRedpacket = serviceFactory.getPersistService()
                    .get(RewardRedpacket.class, redPacketId);
            Reward reward = serviceFactory.getPersistService().get(Reward.class, rewardRedpacket.getRewardId());
            if (rewardRedpacket.getStatus() != RewardRedPacketStatus.CANUSE) {
                result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
                result.setMessage("该红包不可用。");
                result.setReturnValue(response);
                return result;
            }
            if (reward.getRewardUseType() == RewardUseType.CASH200) {// 200元起投
                if (investMoney < 200) {
                    result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
                    result.setMessage("使用该红包最低起投金额为200元");
                    result.setReturnValue(response);
                    return result;
                }
            } else if (reward.getRewardUseType() == RewardUseType.MULTIPLE100) {// 100倍起投
                if (investMoney < rewardRedpacket.getMoney()) {
                    result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
                    result.setMessage("使用该红包最低起投金额为红包面值的100倍");
                    result.setReturnValue(response);
                    return result;
                }
            }

            if ((rewardRedpacket.getMoney()) / 100 > investMoney.longValue()) {
                result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
                result.setMessage("红包金额已大于投资金额");
                result.setReturnValue(response);
                return result;
            }
            /**
             * 红包先使用掉
             */
            RedUseRequestMsg reqMsg = new RedUseRequestMsg();
            reqMsg.setRedPacketId(redPacketId);
            reqMsg.setTransType(TransCodeConstants.RedPacketCode.REDPACKET_USE);
            response = (ResponseMessage) serviceFactory.getProtFactory().remoteTrans(reqMsg);
            if (!RespCodeConstants.CommonCode.TRANS_SUC.equals(response.getRespCode())) {
                result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
                result.setMessage(response.getRespDesc());
                result.setReturnValue(response);
                return result;
            }
        }

        Account account = serviceFactory.getAccountService().getAccount(member.getUser().getId());
        if ((investMoney.doubleValue()) > (account.getBaseMoney() - account.getFreezeMoney()) / 100) {
            result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
            result.setMessage("余额不足!");
            result.setReturnValue(response);
            return result;
        }
        InvestInfoRequestMsg reqMsg = new InvestInfoRequestMsg();
        List<InvestBorrowerDetail> borrowerDetails = new ArrayList<InvestBorrowerDetail>();
        InvestBorrowerDetail borrowerDetail = new InvestBorrowerDetail();
        borrowerDetail.setBorrowerCustId(borrowInfo.getBorrowUserTrustAccountId());
        borrowerDetail.setBorrowerAmt(MoneyUtil.convertFenToYuan(investMoney * 100));
        borrowerDetail.setBorrowerRate(LSConstants.CHAR_ONE);
        borrowerDetail.setProId(borrowInfo.getId().toString());
        borrowerDetails.add(borrowerDetail);
        reqMsg.setBorrowerDetails(JsonUtils.createGson().create().toJson(borrowerDetails));
        reqMsg.setTransAmt(String.valueOf(investMoney * 100));
        reqMsg.setRedPacketId(redPacketId);
        reqMsg.setUsrCustId(user.getTrustAccountId());
        reqMsg.setIsFreeze(LSConstants.CHAR_YES);
        reqMsg.setInvestUserName(user.getUserName());
        reqMsg.setInvestUserId(user.getId().toString());
        reqMsg.setBorrowInfoId(borrowInfo.getId().toString());
        reqMsg.setBorrowName(borrowInfo.getBorrowName());
        reqMsg.setPageType("2");//app应用风格
        reqMsg.setPartnerTransType(PartnerTransType.InitiativeTender);
        reqMsg.setTransType(TransCodeConstants.PartnerTransCode.REQUEST);
        reqMsg.setBgRetUrl(service_notify_url);
        reqMsg.setRetUrl(page_return_url);
        response = (ResponseMessage) serviceFactory.getProtFactory().remoteTrans(reqMsg);
        result.setCode(RespCodeConstants.CommonCode.TRANS_SUC);
        result.setMessage(RespCodeConstants.CommonCode.TRANS_SUC_MSG);
        result.setReturnValue(response);
        result.setReturnObject(PartnerUtil.isTrustPattern());
        return result;
    }
    
    /**
     * 持有资产-页面
     */
    @RequestMapping(value = "/allInvest")
    public String getAllInvest(HttpServletRequest request,ModelMap map,Integer type,String curPage,InvestStatus status){
        SessionMember session = getSessionMember(request);
        if (session==null) {
            return "/user/login/index.jsp";
        }
        UserInfo user = session.getUser();
        Account account = serviceFactory.getAccountService().getAccount(user.getId());
        map.addAttribute("account", account);
        map.addAttribute("status", status);
        return "/page/account/invest/allinvest.jsp";
    }
    
    /**
     *  持有资产
     */
    @RequestMapping(value = "getInvestList")
    @ResponseBody
    public void getInvestList(HttpServletRequest request,ModelMap map,Integer type,InvestStatus[] status,String curPage,PrintWriter printWriter){
        UserInfo user = getSessionMember(request).getUser();
        int int_curPage = (!StringHelper.isEmpty(curPage) ? Integer.parseInt(curPage) : 1);
        int pageSize = 10;
        Map<String , List<?>> dataMap = new HashMap<String, List<?>>();
        List<Integer> pagecount = new ArrayList<Integer>();
        ServiceResult<List<InvestInfoVo>> serviceResult = new ServiceResult<List<InvestInfoVo>>();
        if (status==null || status.length<1) {
            status = new InvestStatus[] {InvestStatus.INVESTING,InvestStatus.SUCESS,InvestStatus.LOANED,InvestStatus.LOANING,InvestStatus.RETURNED};
        }else if (InvestStatus.SUCESS.equals(status[0])) {
            status = new InvestStatus[] {InvestStatus.INVESTING,InvestStatus.SUCESS};
        }else if(InvestStatus.LOANING.equals(status[0])){
            status = new InvestStatus[] {InvestStatus.LOANING,InvestStatus.LOANED};
        }
        serviceResult = serviceFactory.getInvestInfoService().queryMyInvestList(user.getId(), status, null, int_curPage, pageSize);
        pagecount.add(serviceResult.getReturnListSize());
        dataMap.put("list", serviceResult.getReturnValue());
        dataMap.put("pageCount", pagecount);
        Gson gson = new Gson();
        printWriter.write(gson.toJson(dataMap));
        printWriter.flush();
        printWriter.close();
    }
}
